package org.qloudgen.txn.dilithium.cluster.common;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.wicket.request.component.IRequestablePage;

import org.qloudgen.txn.dilithium.cluster.beans.Dict;
import org.qloudgen.txn.dilithium.cluster.database.DefaultImpl;
import org.qloudgen.txn.dilithium.cluster.pages.AddClientPage;
import org.qloudgen.txn.dilithium.cluster.pages.AddNodePage;
import org.qloudgen.txn.dilithium.cluster.pages.InitClusterPage;
import org.qloudgen.txn.dilithium.cluster.pages.RemoveClientPage;
import org.qloudgen.txn.dilithium.cluster.pages.RemoveNodePage;
import org.qloudgen.txn.dilithium.cluster.pages.ShowConfPage;
import org.qloudgen.txn.dilithium.cluster.pages.ShowDetailPage;
import org.qloudgen.txn.dilithium.cluster.pages.common.ConfirmPage;
import org.qloudgen.txn.dilithium.cluster.sqlmap.MyBatisUtil;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public final class CommonValues {
	
	static Log log = LogFactory.getLog(CommonValues.class);
	
	public static boolean initFlag = false;

	private final static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
	
	public static Properties props;
	public static SqlSessionFactory factory;
	public static Runtime runtime = Runtime.getRuntime();
	public static Map<String,Class<? extends IRequestablePage>> pages = Maps.newHashMap();
	public static Map<String,String> statusNames = Maps.newHashMap();
	public static Map<String,String> tableTypes = Maps.newHashMap();
	public static Map<String,String> tableOperaTypes = Maps.newHashMap();
	public static List<String> configTypes=Lists.newArrayList();
	public static Map<String,String> configTypeNames = Maps.newHashMap();
	public static Map<String,String> paramUnits = Maps.newHashMap();

	public static Map<String,Map<String,String>> dicts = Maps.newHashMap();
	
	public static final int SHOW_CLUSTER_LIST_NUMBER = 10;
		
    public static final int PORT_MIN = 1024;
    public static final int PORT_MAX = 65535;
	public static final int CLUSTER_LIST_REFRESH_TIME = 5;
	public static final int CLUSTER_CONF_PARAM_LIST = 20;

	public static final String SYSUSER = "pgxc";
	public static final String SYSUSER_PASSWORD_LOCAL = SYSUSER;
	public static final String DEFAULT_DB = "dilithium";
	public static final String DEFAULT_DB_USER = SYSUSER;
	public static final String DEFAULT_DB_SUPERUSER_PASSWORD = "postgres";

	public static final String RESOURCE = System.getProperty("user.dir") + "/src/main/resources";
    public static final String SHELL = RESOURCE + "/shell";
	public static final String CHECK_SUPERUSER_SH = SHELL + "/check_superuser.sh";
	public static final String CHECK_OTHER_SUPERUSER_SH = SHELL + "/check_other_superuser.sh";
	public static final String CHECK_PASSWORD_SH = SHELL + "/check_password.sh";    
	public static final String CREATE_SUPERUSER_SH = SHELL + "/create_superuser.sh";
	public static final String CONSTRUCT_ISA_LOCAL = SHELL + "/construct_isa_ssh.sh";
	public static final String CREATE_LOG_FILE_SH = SHELL + "/create_log_file.sh";
	public static final String OPERATOR_SH = SHELL + "/cluster_operator.sh";
	public static final String GENERATE_SSHKEY_SH = SHELL + "/generateSSHKey.sh";
	public static final String COPY_SSHKEY_SH = SHELL + "/copySSHKey.sh";
	public static final String INIT_CLUSTER_SH = SHELL + "/initCluster.sh";
	public static final String SCP_FILE_SH = SHELL + "/scpFile.sh";
	public static final String RESET_DBSUPERUSER_PASSWORD_SH = SHELL + "/resetDBSuperuserPassword.sh";

	public static final String PGXC_SHELL_DIR = "pgxc_ctl";
	public static final String PGXC_OWNER = SYSUSER;
	public static final String PGXC_USER = SYSUSER;
	public static final String PGXC_SYSUSER_HOME = "/home/"+SYSUSER;
	public static final String LOGDIR = PGXC_SYSUSER_HOME + "/pgxc_ctl_log";
	public static final String INSTALL_LOGDIR = System.getProperty("user.dir") + "/log";
	public static final String COPYSSHKEY_FILE = PGXC_SYSUSER_HOME + "/copySSHKey.sh";
	public static final String SHELL_DIR = PGXC_SYSUSER_HOME + "/pgxc_ctl/";
			
	public static final String STATUS_ON = "on";
	public static final String STATUS_OFF = "off";
	public static final String STATUS_CREATE = "create";

	public static final String INFO_CREATE_CONFIGFILE = " 集群配置文件创建完成。 ";
	public static final String INFO_CONFIG_CONFIGFILE = " 集群配置文件配置完成。 ";
	public static final String INFO_COMPLETE_INSTALLATION = " 集群安装完成。";
	public static final String INFO_COMPLETE_ADDING_NEW_NODE = " 节点添加完成。";
	public static final String INFO_COMPLETE_REMOVING_NODE = "  节点删除完成！";

	public static final String ERROR_PARAMETER_LENGTH = " 确保参数全部选中！";
	public static final String ERROR_CONSTRUCT_NOPASS = " 构建无密码登录失败！";
	public static final String ERROR_FILE = " 创建文件失败！";

	public static final String ERROR_INIT_ALL = " 初始化集群失败！";
	public static final String ERROR_GET_MONITOR_INFO = " 获取节点状态信息失败！ ";
	public static final String ERROR_INIT_NEW_NODE = " 初始化新节点失败！";
	public static final String ERROR_LOGIN = "密码不正确！";
	public static final String ERRO_CREATE_USRE = "用户已存在！";
	public static final String ERROR_TWO_PASSWORDS_MISMATCHER = "两次密码不一致！";
	public static final String ERROR_COPYSSH_KEY = "构建no-pass ssh to 控制台节点错误！";
	public static final String ERROR_SCP_FILE = " scp copySSHKey.sh to 控制台节点错误！";

	public static final String IPFORMATERROR = ". 不正确的ip！";
	public static final String IPPINGERROR = ". ip地址ping不通！";
	public static final String PGHBAFORMATERROR = ". Pg hba 格式不正确！";	
	
	public static final String INFO_CLUSTER_MAIN_PAGE_NO_CLUSTER = "请先选择一个集群！";
	public static final String INFO_CLUSTER_MAIN_PAGE_RUNNING = " 已经运行！";
	public static final String INFO_CLUSTER_MAIN_PAGE_INITING = " 不能再次初始化！";
	public static final String INFO_CLUSTER_MAIN_PAGE_NO_INIT = "没有初始化！";
	public static final String INFO_CLUSTER_MAIN_PAGE_STOPPED = " 已经停止！";
	public static final String INFO_CLUSTER_MAIN_PAGE_NOT_DELETED = " 运行中，不能删除！";
	public static final String INFO_NO_NODES = "请选择节点！";
	public static final String INFO_CLUSTER_MAIN_PAGE_RUN = "集群必须运行,才能操作！";
	public static final String INFO_CLUSTER_MAIN_PAGE_REDISTRIBUTE = "集群必须运行才能重新分布！";

	public static final String INFO_TABLE_REDISTRIBUTE = " 重新分布完成！";
	public static final String INFO_START = "点击确定之后，启动集群";	
	public static final String INFO_STOP = "点击确定之后，停止集群";	
	public static final String INFO_DELETE = "点击确定之后，删除集群";

	public static final  String ERROR = "处理失败，请重试!";	

	public static final int TABLE_LIST_NUMBER = 20;
	public static final int NODE_LIST_NUMBER = 20;

	public static final String DATANODE_PARAM = "datanode";
	public static final String DATABASE_PARAM_SHARED_BUFFERS = "shared_buffers";
	public static final String COORDINATOR_PARAM = "coordinator";
	
	public static final String CLUSTER_START = "start";
	public static final String CLUSTER_STOP = "stop";
	public static final String CLUSTER_CONFIG = "config";
	public static final String CLUSTER_DELETE = "delete";
	public static final String CLUSTER_REMOVE_NODE = "remove";
	public static final String CLUSTER_INIT = "init";
	public static final String CLUSTER_ADD_NODE = "add";
	public static final String CLUSTER_MONITOR = "monitor";
	public static final String CLUSTER_ADD_CLIENT = "addclient";
	public static final String CLUSTER_REMOVE_CLIENT = "removeclient";
	public static final String CLUSTER_NODE_STATUS = "nodestatus";
	
	public static final String COORD_EXTRA_CONFIG = "coordExtraConfig";
	public static final String DATANODE_EXTRA_CONFIG = "datanodeExtraConfig";
	
	public static final Boolean CONSTRUCT_NO_PASS = false;

	private CommonValues(){};
	
	private static CommonValues commonValues = new CommonValues();

	public static CommonValues getInstance(){
		return commonValues;
	}
	
	public static String getTime(){
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return df.format(new Date());
	}
	
//	private void  loadProperties()  {
//	    
//		CommonValues.props = new Properties();  
//		
//	    ClassLoader loader = getClass().getClassLoader();
//		try {
//			
//			InputStream in = loader.getResourceAsStream("conf.properties");
//			CommonValues.props.load(in);
//			
//		} catch (IOException e) {
//			log.error(e.getMessage());
//		}
//	} 
	
	public void init(){
		
		if (!CommonValues.initFlag) {
			
			try {
				CommonValues.getInstance().setCommonValues();
				if (CommonValues.CONSTRUCT_NO_PASS)
					ShellExec.checkCreateSysuserLocal();
			} catch (Exception e) {
				log.error(e.getMessage());
				log.error("Failed in loading Common values");
				System.exit(-1);
			}
			
		}
	}
	
	private void setCommonValues() throws Exception{
		
//		loadProperties();	
		CommonValues.factory = MyBatisUtil.getSqlSessionFactory();
		
		CommonValues.pages.put(CommonValues.CLUSTER_INIT, InitClusterPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_START, ConfirmPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_STOP, ConfirmPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_DELETE, ConfirmPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_ADD_NODE, AddNodePage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_REMOVE_NODE, RemoveNodePage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_ADD_CLIENT, AddClientPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_REMOVE_CLIENT, RemoveClientPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_NODE_STATUS, ShowDetailPage.class);
		CommonValues.pages.put(CommonValues.CLUSTER_CONFIG, ShowConfPage.class);
		
		CommonValues.statusNames.put(CommonValues.STATUS_CREATE, "已创建");
		CommonValues.statusNames.put(CommonValues.STATUS_ON, "运行中");
		CommonValues.statusNames.put(CommonValues.STATUS_OFF, "停止");
		
		CommonValues.tableTypes.put("H", "HASH分区表");
		CommonValues.tableTypes.put("M", "MODULO分区表");
		CommonValues.tableTypes.put("R", "复制表");
		
		CommonValues.tableOperaTypes.put("add", "add");
		CommonValues.tableOperaTypes.put("remove", "delete");
		
		CommonValues.configTypes.add("default");
		CommonValues.configTypes.add("udf");
		
		CommonValues.configTypeNames.put("default", "默认参数配置");
		CommonValues.configTypeNames.put("udf", "自定义参数配置");
		
		CommonValues.paramUnits.put("shared_buffers", "MB");
		CommonValues.paramUnits.put("wal_buffers", "kB");
		
		// get dicts
		construct_dicts(CommonValues.dicts);
		
		CommonValues.initFlag = true;
	
	}
	
	public static void throwException(String error) throws Exception {

			throw new Exception(error);
	}

	public static String getLogFileName(int clusterID) {
		return String.valueOf(clusterID) + "_pgxc_ctl_log.log";
	}

	public static String getConfigFileName(int clusterID) {
		return "pgxc_ctl_" + clusterID + ".conf";
	}
	
	private void construct_dicts(Map<String, Map<String, String>> dicts) {
	
		List<Dict> dictList = DefaultImpl.getDicts();
		
		if (dictList == null ) return ;
		
		for (Dict dict : dictList){
			if (dicts.containsKey(dict.getDictName())){
				dicts.get(dict.getDictName()).put(dict.getDictKey(), dict.getDictValue());
			} else {
				Map<String,String> map = Maps.newHashMap();
				map.put(dict.getDictKey(), dict.getDictValue());
				dicts.put(dict.getDictName(), map);
			}
		}
		
	}

	public static String getHelloInfo(String userNo) {
		
		return "用户 ： "+ userNo + " !   登录时间：" + df.format(new Date());
	}
	
}